﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Obsidian.Edm
{
    public class OrderField : ModelField, IModelField
    {

        public override FieldType Type
        {
            get { return FieldType.Order; }
        }

        private Dictionary<string, int> dictFields = new Dictionary<string, int>();
        private List<OrderInfo> listOrders = new List<OrderInfo>();
        private Dictionary<string, OrderInfo> dictOrders = new Dictionary<string, OrderInfo>();

        /// <summary>
        /// 获取值
        /// </summary>
        public string Value
        {
            get
            {
                if (this.IsNull)
                    return null;

                StringBuilder sb = new StringBuilder();
                bool first = true;
                foreach (OrderInfo orderInfo in listOrders)
                {
                    if (first)
                        first = false;
                    else
                        sb.Append(",");
                    sb.Append(orderInfo.FieldAlias)
                        .Append(":")
                        .Append(orderInfo.OrderType == OrderType.ASC ? "ASC" : "DESC");
                }
                return sb.ToString();
            }
        }

        /// <summary>
        /// 获取值
        /// </summary>
        public object OValue
        {
            get { return this.Value; }
        }

        /// <summary>
        /// 设置值
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public IModel Set(string value)
        {
            this.SetNull();

            if (String.IsNullOrEmpty(value))
            {
                return base.Model;
            }

            string[] pairs = value.Split(',');
            if (pairs.Length == 0)
                return base.Model;

            foreach (string pair in pairs)
            {
                if (String.IsNullOrEmpty(pair))
                    throw new Exception("输入参数格式错误!");

                string[] arr = pair.Split(':');
                if (arr.Length != 2)
                    throw new Exception("输入参数格式错误!");
                string fieldAlias = arr[0];
                if (String.IsNullOrEmpty(fieldAlias))
                    throw new Exception("字段名不能为空");
                OrderType orderType = StringToOrderType(arr[1]);
                this.Add(fieldAlias, orderType);
            }

            return base.Model;
        }

        /// <summary>
        /// 设置值
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public IModel Set(object value)
        {
            if (value == null)
            {
                return this.SetNull();
            }
            else
            {
                string strVal = Convert.ToString(value);
                return this.Set(strVal);
            }
        }

        /// <summary>
        /// 设置值
        /// </summary>
        public bool TrySet(object value)
        {
            try
            {
                this.Set(value);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 设置为空值状态
        /// </summary>
        public IModel SetNull()
        {
            this.listOrders.Clear();
            this.dictOrders.Clear();
            this._isNull = true;
            return base.Model;
        }

        public void Add(string fieldAlias, OrderType orderType)
        {
            if (!dictFields.ContainsKey(fieldAlias))
                throw new Exception(String.Format("字段{0}非可排序字段", fieldAlias));

            if (dictOrders.ContainsKey(fieldAlias))
                throw new Exception(String.Format("已存在字段：{0}排序设置", fieldAlias));


            OrderInfo orderInfo = new OrderInfo(fieldAlias, orderType);
            dictOrders.Add(fieldAlias, orderInfo);
            listOrders.Add(orderInfo);
            if (!base._assigned)
                base._assigned = true;
            this._isNull = false;
        }

        public void Remove(string fieldAlias)
        {
            if (dictOrders.ContainsKey(fieldAlias))
            {
                dictOrders.Remove(fieldAlias);
                for (int i = 0; i < listOrders.Count; i++)
                {
                    OrderInfo orderInfo = listOrders[i];
                    if (orderInfo.FieldAlias.Equals(fieldAlias))
                    {
                        listOrders.RemoveAt(i);
                        break;
                    }
                }
            }
        }

        public int Count
        {
            get { return listOrders.Count; }
        }

        public OrderInfo Get(int index)
        {
            return listOrders[index];
        }

        public OrderInfo Get(string fieldAlias)
        {
            return dictOrders[fieldAlias];
        }

        public OrderInfo[] GetArray()
        {
            return listOrders.ToArray();
        }

        public bool Has(string fieldAlias)
        {
            return dictOrders.ContainsKey(fieldAlias);
        }

        public OrderField(IModel model, string fields)
        {
            this.SetFields(fields);
            this.InitField(model);
        }

        public OrderField(IModel model, string alias, string fields)
        {
            this.SetFields(fields);
            this.InitField(model, null, alias);
        }

        private void SetFields(string fields)
        {
            string[] arr = fields.Split(',');
            int i = 0;
            foreach (string str in arr)
            {
                if (String.IsNullOrEmpty(str))
                    continue;
                string s = str.Trim();
                if (dictFields.ContainsKey(s))
                    throw new Exception(String.Format("存在重复排序字段设置：{0}", s));
                dictFields.Add(s, i);
                i++;
            }
        }

        private static OrderType StringToOrderType(string str)
        {
            if (str.Equals("DESC", StringComparison.OrdinalIgnoreCase))
                return OrderType.DESC;
            else if (str.Equals("ASC", StringComparison.OrdinalIgnoreCase))
                return OrderType.ASC;
            else
                throw new Exception("排序类型字符串输入错误");
        }
    }
}
